#include <stdio.h>
#include <pthread.h>
#include <stdlib.h>
#include <string.h>
#include "t_error.h"
#include "common/console.h"
#include "common/lock.h"

typedef struct _T_LOCK_OBJ_S
{
	pthread_mutex_t stLock;
	char chName[64];
} T_LOCK_OBJ_S;

T_LOCK_HANDLE LockCreate(char *pchName)
{
	int nRet = 0;
	T_LOCK_OBJ_S *pLockObj = NULL;
	pthread_mutexattr_t stLockAttr;

	pLockObj = (T_LOCK_OBJ_S *)malloc(sizeof(T_LOCK_OBJ_S));
	if (pLockObj == NULL)
	{
		console_error("malloc for create lock error!\n");
		return NULL;
	}

	memset(pLockObj, 0, sizeof(T_LOCK_OBJ_S));
	strcpy(pLockObj->chName, "Anonymous lock");

	nRet = pthread_mutexattr_init(&stLockAttr);
	if (nRet != 0)
	{
		console_error("pthread_mutexattr_init error!\n");
		goto _ERROR;
	}

	nRet = pthread_mutexattr_settype(&stLockAttr, PTHREAD_MUTEX_ERRORCHECK_NP);
	if (nRet != 0)
	{
		console_error("pthread_mutexattr_settype error!\n");
		goto _ERROR;
	}

	nRet = pthread_mutex_init(&pLockObj->stLock, &stLockAttr);
	if (nRet != 0)
	{
		console_error("pthread_mutex_init error!\n");
		goto _ERROR;
	}
	if (pchName)
	{
		int nLen = strlen(pchName);
		nLen = nLen < sizeof(pLockObj->chName) ? nLen : sizeof(pLockObj->chName);
		strncpy(pLockObj->chName, pchName, nLen);
	}

	pthread_mutexattr_destroy(&stLockAttr);
	return (T_LOCK_HANDLE)pLockObj;

_ERROR:
	if (pLockObj)
	{
		free(pLockObj);
	}
	pthread_mutexattr_destroy(&stLockAttr);
	return NULL;
}

int LockDestroy(T_LOCK_HANDLE hLock)
{
	T_LOCK_OBJ_S *pLockObj = (T_LOCK_OBJ_S *)hLock;

	if (pLockObj == NULL)
	{
		console_error("invalid arguments!\n");
		return T_ERR_INVALID_ARG;
	}

	pthread_mutex_destroy(&pLockObj->stLock);
	free(pLockObj);

	return T_ERR_OK;
}

int LockEnter(T_LOCK_HANDLE hLock)
{
	T_LOCK_OBJ_S *pLockObj = (T_LOCK_OBJ_S *)hLock;

	if (pLockObj == NULL)
	{
		console_error("invalid arguments!\n");
		return T_ERR_INVALID_ARG;
	}

	return pthread_mutex_lock(&pLockObj->stLock);
}

int LockLeave(T_LOCK_HANDLE hLock)
{
	T_LOCK_OBJ_S *pLockObj = (T_LOCK_OBJ_S *)hLock;

	if (pLockObj == NULL)
	{
		console_error("invalid arguments!\n");
		return T_ERR_INVALID_ARG;
	}

	return pthread_mutex_unlock(&pLockObj->stLock);
}

#if 0

int sum;
int quit = 0;
D_LOCK_HANDLE gshLock = NULL;


void* dec(void *argv)
{
	while(!quit)
	{
		LockEnter(gshLock);
		sum--;
		D_DBG("dec lock enter!, sum=%d\n", sum);
		LockLeave(gshLock);
		usleep(5*1000);
	}
	D_WARN("dec thread exit!\n");
    return 0;
}

void* add(void *argv)
{
	while(!quit)
	{
		LockEnter(gshLock);
		sum++;
		D_DBG("add lock enter!, sum=%d\n", sum);
		sleep(5);
		LockLeave(gshLock);
		usleep(5*1000);
	}
	D_WARN("add thread exit!\n");
    return 0;
}

int main(int argc,char** argv)
{
    pthread_t ptid1,ptid2;
    sum = 0;

	gshLock = LockCreate("test");
	if(gshLock == NULL)
	{
		D_ERR("LockCreate error\n");
		return -1;
	}
    
    pthread_create(&ptid1,NULL,dec,NULL);
    pthread_create(&ptid2,NULL,add,NULL);
    
    
    int counter = 0;  
  	while(counter != 10)
  	{  
    	D_DBG("counter: %d\n", counter);  
    	sleep(1);  
    	counter++;  
  	}  

	quit = 1;
	sleep(1);

	LockDestroy(gshLock);
	gshLock = NULL;
    
    return 0;    
}

#endif
